package com.cmos.um.utils.http;


import com.alibaba.fastjson.JSONObject;
import com.cmos.um.utils.http.config.RestTemplateConfiguration;
import com.cmos.um.utils.WSRtnJsonCtx;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.Charset;
import java.text.MessageFormat;
import java.util.Map;

/**
 * HttpClient use RestTemplate
 *
 * @author Feng Yu
 * @version V1.0
 * @date 2017-05-17
 */
@Component
@ConditionalOnBean({RestTemplateConfiguration.class})
public class RestClientHttpRequest {

    private static Logger logger = LoggerFactory.getLogger(RestClientHttpRequest.class);

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 发起get请求
     *
     * @param requestUrl   请求的URL
     * @param responseType 返回值得类型
     * @return
     */
    public ResponseEntity doGet(String requestUrl, Class responseType) {
        return this.doGet(requestUrl, responseType, null);
    }

    /**
     * 发起get请求
     *
     * @param requestUrl   请求目标url
     * @param responseType 返回值类型
     * @param uriVariables URL的map集合
     * @return 返回值
     */
    public ResponseEntity doGet(String requestUrl, Class responseType, Map<String, ?> uriVariables) {
        return restTemplate.getForEntity(requestUrl, responseType, uriVariables);
    }

    /**
     * 发起post请求，请求的类型为json类型
     *
     * @param requestUrl  请求目标的url
     * @param requestBody 请求体
     * @return 返回值
     */
    public String doPost(String requestUrl, Object requestBody) {
        MediaType mt = new MediaType("application", "json", Charset.forName("UTF-8"));
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(mt);
        ResponseEntity<String> responseEntity = this.doPost(requestUrl, headers, requestBody, String.class);
        return responseEntity.getBody();
    }

    /**
     * 发起post请求，请求的类型为x-www-form-urlencoded类型
     *
     * @param requestUrl   请求目标的url
     * @param mapParameter 请求消息内容，消息内容需要传入map类型
     * @param urlVariables url自动匹配替换的参数，如url为api/{a}/{b},参数为["1","2"],则解析的url为api/1/2，使用Map参数时，遵循按key匹配
     * @return 返回值
     */
    public String doMultipartPost(String requestUrl, Map mapParameter, Map urlVariables) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<String> request;
        //requestBody中存在数据
        if (mapParameter != null && mapParameter.size() > 0) {
            //x-www-form-urlencoded 型不允许发送map类型的数据
            request = new HttpEntity<>(mapParameter.toString(), headers);
        } else {    //requestBody中不存在数据
            request = new HttpEntity<>(null, headers);
        }

        ResponseEntity<String> responseEntity = restTemplate.exchange(requestUrl, HttpMethod.POST, request, String.class, urlVariables);
        return responseEntity.getBody();
    }

    /**
     * 发起一个post请求
     *
     * @param requestUrl    请求目标URL
     * @param requestHeader 请求头
     * @param requestBody   请求体
     * @param responseType  返回值类型
     * @return 返回值
     */
    public ResponseEntity doPost(String requestUrl, HttpHeaders requestHeader, Object requestBody, Class responseType) {
        HttpEntity requestEntity = new HttpEntity(requestBody, requestHeader);
        return restTemplate.exchange(requestUrl, HttpMethod.POST, requestEntity, responseType);
    }

    /**
     * 发起一个put类型的请求
     *
     * @param requestUrl 请求目标URL
     * @param requestObj 请求体
     */
    public void doPut(String requestUrl, Object requestObj) {
        restTemplate.put(requestUrl, requestObj);
    }

    /**
     * 发起一个put类型的请求
     *
     * @param requestUrl   请求目标URL
     * @param requestObj   请求体
     * @param uriVariables 请求参数集合
     */
    public void doPut(String requestUrl, Object requestObj, Map<String, ?> uriVariables) {
        restTemplate.put(requestUrl, requestObj, uriVariables);
    }

    /**
     * 可以发起所有类型的请求
     *
     * @param requestUrl    请求目标URL
     * @param requestMethod 发起请求的方法
     * @param requestHeader 请求头
     * @param requestBody   请求体
     * @param responseType  返回值的类型
     */
    public ResponseEntity doExchange(String requestUrl, HttpMethod requestMethod, HttpHeaders requestHeader, Object requestBody, Class responseType) {
        HttpEntity requestEntity = new HttpEntity(requestBody, requestHeader);
        return restTemplate.exchange(requestUrl, requestMethod, requestEntity, responseType);
    }

    /**
     * 发送/获取 服务端数据(主要用于解决发送put,delete方法无返回值问题).
     *
     * @param url      绝对地址
     * @param method   请求方式
     * @param bodyType 返回类型
     * @return 返回结果(响应体)
     */
    public String exchange(String url, JSONObject params,HttpMethod method, Class<String> bodyType) {
        // 请求头
        HttpHeaders headers = new HttpHeaders();
        MimeType mimeType = MimeTypeUtils.parseMimeType("application/json");
        MediaType mediaType = new MediaType(mimeType.getType(), mimeType.getSubtype(), Charset.forName("UTF-8"));
        // 请求体
        headers.setContentType(mediaType);
        //提供json转化功能
        ObjectMapper mapper = new ObjectMapper();
        String str = null;
        try {
            if (!params.isEmpty()) {
                str = mapper.writeValueAsString(params);
            }
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        // 发送请求
        HttpEntity<String> entity = new HttpEntity<>(str, headers);
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> resultEntity = restTemplate.exchange(url, method, entity, bodyType);
        return resultEntity.getBody();
    }

    /**
     * 用于向新方cti发送请求
     * @param url
     * @param ip
     * @param action
     * @param opr
     * @param paraObj
     * @return
     */
    public WSRtnJsonCtx doPost(String url, String ip, String action, String opr, Object paraObj) {
        JSONObject reqMsgObj = buildReqMsgObj(action, opr, paraObj);
        String sendUrl = MessageFormat.format(url, ip);
        logger.info("调用的接口地址为："+sendUrl+"入参为："+reqMsgObj);
        String result = this.doPost(sendUrl, reqMsgObj);
        WSRtnJsonCtx wsRtnJsonCtx = new WSRtnJsonCtx(result);
        return wsRtnJsonCtx;
    }

    public  JSONObject buildReqMsgObj(String method, String operation, Object context) {
        JSONObject inputObj = new JSONObject(2);
        inputObj.put("operation", operation);
        inputObj.put("context", context);

        JSONObject reqMsgObj = new JSONObject(2);
        reqMsgObj.put("method", method);
        reqMsgObj.put("input", inputObj);

        return reqMsgObj;
    }

}
